<template>
    <div class="charts-wrapper">
        <QABlock :visible="QAState"
                 @close="useQA">
        </QABlock>
        <div class="vertical-wrapper" :class="withDrawer?'with-drawer':'no-drawer'">
            <tools :tools-methods="toolsMethods"></tools>
            <div class="bench-wrapper">
                <div id="graph" class="charts-bench">
                    <charts-info v-if="isDisplayInfo" :filter="filterNodeType"></charts-info>
                </div>
            </div>
        </div>
        <right-drawer :visible="drawerState[0]">
            <div class="tools-wrapper" slot="title">
                <el-icon class="el-icon-s-cooperation"></el-icon>
                <p style="margin-left: 14px">编辑栏</p>
            </div>
            <node-form :node-data="click_node"
                       :nodeMethods="dataToForm.nodeMethods"></node-form>
        </right-drawer>
        <right-drawer :visible="drawerState[1]">
            <div class="tools-wrapper" slot="title">
                <el-icon class="el-icon-s-cooperation"></el-icon>
                <p style="margin-left: 14px">编辑栏</p>
            </div>
            <edge-form :edge-data="click_edge"
                       :edgeMethods="dataToForm.edgeMethods"></edge-form>
        </right-drawer>
        <right-drawer :visible="drawerState[2]">
            <div class="tools-wrapper" slot="title">
                <el-icon class="el-icon-search"></el-icon>
                <p style="margin-left: 14px">搜索结果</p>
            </div>
            <search-form :search-data="searchResult"
                         :searchMethods="dataToForm.searchMethods"></search-form>
        </right-drawer>
        <el-dialog
                title="新手教程"
                :visible.sync="dialogVisible"
                width="65%"
                :before-close="handleClose"
        >
            <div style="display: flex;align-items: center;justify-content: center">
                <i class="el-icon-d-arrow-left" style="font-size: 60px;margin-right: 30px" @click="minus1()"></i>
                <el-image v-show="imageIndex==0" :src="srcList[0]"></el-image>
                <el-image v-show="imageIndex==1" :src="srcList[1]"></el-image>
                <el-image v-show="imageIndex==2" :src="srcList[2]"></el-image>
                <i class="el-icon-d-arrow-right" style="font-size: 60px;margin-left: 30px" @click="plus1()"></i>
            </div>
            <span slot="footer" class="dialog-footer">
    <el-button type="primary" @click="dialogVisible = false">我知道啦</el-button>
    </span>
        </el-dialog>
        <text-importer :visible="importerState" :graphId="graphId" @close="resolveGraphByText"></text-importer>
    </div>
</template>

<script>
    import {mapGetters, mapMutations, mapActions} from "vuex";
    import Tools from "./toolsBar/tools";
    import * as d3 from "d3";
    import {Status} from "../assets/javascript/graphD3/Util/constant";
    import Node from "../assets/javascript/graphD3/Node/Node";
    import Graph from "../assets/javascript/graphD3/index";
    import Thumbnail from "../assets/javascript/graphD3/Thumbnail/index";
    import RightDrawer from "./basicFrame/rightDrawer";
    import NodeForm from "./d3Form/nodeForm";
    import EdgeForm from "./d3Form/edgeForm";
    import Edge from "../assets/javascript/graphD3/Edge/Edge";
    import ChartsInfo from "./toolsBar/chartsInfo";
    import d3ClassGetter from "../assets/javascript/d3ClassGetter";
    import global from "../store/global";
    import SearchForm from "./d3Form/searchForm";
    import TextImporter from "./basicFrame/textImporter";
    import QABlock from "./basicFrame/QABlock";

    const defaultDatas = {
        nodes: [],
        edges: []
    };

    const drawerState = [false, false, false];

    export default {
        name: "templateBench",
        inject: ["reload1"],
        data() {
            return {
                imageIndex: 0,
                srcList: [
                    require(`../../public/img/4.jpg`),
                    require(`../../public/img/5.jpg`),
                    require(`../../public/img/6.jpg`)
                ],
                dialogVisible: true,
                graph: null,
                new_edge_source_id: 0,
                click_edge: {
                    label: "",
                    source: {
                        label: ""
                    },
                    target: {
                        label: ""
                    }
                },
                click_node: {},

                new_node_label: "",
                new_edge_label: "",
                new_edge_type: 0,

                show_edge_label: true,
                graphMode: 0,
                graphId: 362,

                new_edge_flag_temp: false,
                drawerState: drawerState,
                withDrawer: false,
                importerState: false,
                QAState: false,
                isDisplayInfo: true,

                dataToForm: {
                    nodeMethods: {
                        addEdge: this.addEdge,
                        modifyNodeName: this.modifyNodeName,
                        modifyNodeType: this.modifyNodeType,
                        modifyNodeFirstDraw: this.modifyNodeFirstDraw,
                        modifyNodeContent: this.modifyNodeContent,
                        deleteNode: this.deleteNode,
                        changeNodeSize: this.changeNodeSize,
                        changeNodeLabel: this.changeNodeLabel
                    },
                    edgeMethods: {
                        modifyEdgeName: this.modifyEdgeName,
                        deleteEdge: this.deleteEdge,
                        modifyEdgeType: this.modifyEdgeType
                    },
                    searchMethods: {
                        highLightNode: this.highLightNode,
                        highLightEdge: this.highLightEdge
                    }
                },
                toolsMethods: {
                    addNode: this.addNodesTest,
                    searchNode: this.searchNode,
                    modeMethodList: {},
                    funcMethodList: {
                        view: this.showEdgeLabel,
                        mode: this.changeGraphMode,
                        xml: this.exportXML,
                        upload: this.importGraphByFile,
                        import: this.resolveGraphByText
                    },
                    toolMethodList: {
                        zoom_in: this.zoomIn,
                        zoom_out: this.zoomOut,
                        refresh: this.resumeZoom
                    },
                    infoMethodList: {
                        info: this.displayGraphInfo,
                        help: this.useQA
                    }
                },
                searchResult: {
                    edges: [],
                    nodes: [],
                    nodes_content: []
                }
            };
        },
        created() {
            if (d3ClassGetter.newUser !== 0) {
                this.dialogVisible = false;
            }
        },
        mounted() {
            this.graphId = this.$route.params.graphId || this.graphId;
            this.getGraphDetail(this.graphId).then((result) => {
                defaultDatas.nodes = result.data.nodes;
                defaultDatas.edges = result.data.links;
                setTimeout(() => this.graph.setDataForce(defaultDatas));
                this.updateInfo(defaultDatas);
            });
            this.$nextTick(() => {
                this.initializeGraph();
                this.initializeEvent();
                this.loadData();
            });
        },
        destroyed() {

        },
        components: {
            QABlock,
            TextImporter,
            SearchForm,
            ChartsInfo,
            EdgeForm,
            NodeForm,
            RightDrawer,
            Tools
        },
        computed: {
            ...mapGetters([
                "new_node_flag",
                "new_edge_flag"
            ])
        },
        methods: {
            ...mapMutations([
                "set_new_node_flag",
                "set_new_link_flag"
            ]),
            ...mapActions([
                "getGraphDetail",
                "addNode",
                "addNodeByName",
                "updateNode",
                "updateRelation",
                "addRelation",
                "deleteRelationById",
                "deleteNodeById",
                "searchGraphNodes",
                "search",
                "exportGraphAsXml",
                "importGraph"
            ]),
            minus1() {
                if (this.imageIndex > 0) {
                    this.imageIndex = this.imageIndex - 1;
                } else {
                    this.$message.warning("已经是第一张");
                }
            },
            plus1() {
                if (this.imageIndex < this.srcList.length - 1) {
                    this.imageIndex = this.imageIndex + 1;
                } else {
                    this.$message.warning("已经是最后一张");
                }
            },
            addNodesTest() {
                this.set_new_node_flag(true);
            },
            addEdge(newEdgeLabel, newEdgeType) {
                this.new_edge_label = newEdgeLabel;
                this.new_edge_type = newEdgeType;
                this.set_new_link_flag(true);
            },
            modifyNodeName(newNodeLabel) {
                let temp = {id: this.click_node.id, label: newNodeLabel};
                this.updateNode(temp).then(result => {
                    this.graph.modifyNodeLabel({node: this.click_node, newLabel: newNodeLabel});
                });
            },
            modifyEdgeName(edgeName) {
                let temp = {id: this.click_edge.id, label: edgeName};
                this.updateRelation(temp).then(result => {
                    this.graph.modifyEdgeLabel({edge: this.click_edge, newLabel: edgeName});
                });

            },
            modifyNodeType(nodeType) {
                let temp = {id: this.click_node.id, type: nodeType};
                this.updateNode(temp).then(result => {
                    this.graph.modifyNodeType({id: this.click_node.id, type: nodeType});
                });
                d3ClassGetter.nodeStyleList[this.click_node.type].count -= 1;
                d3ClassGetter.nodeStyleList[nodeType].count += 1;
            },
            modifyNodeFirstDraw() {
                this.graph.modifyNodeFirstDraw({id: this.click_node.id});
                this.reload1();
            },
            modifyNodeContent(nodeContent) {
                let temp = {id: this.click_node.id, content: nodeContent};
                this.updateNode(temp).then(result => {
                    this.graph.modifyNodeContent({id: this.click_node.id, content: nodeContent});
                });
            },
            modifyEdgeType(edgeType) {
                let temp = {id: this.click_edge.id, type: edgeType};
                this.updateRelation(temp).then(result => {
                    this.graph.modifyEdgeType({id: this.click_edge.id, type: edgeType});
                });
            },
            deleteNode() {
                this.deleteNodeById(this.click_node.id).then(result => {
                    this.graph.deleteNode([this.click_node.id]);
                });
                d3ClassGetter.nodeStyleList[this.click_node.type].count -= 1;
            },
            deleteEdge() {
                this.deleteRelationById(this.click_edge.id).then(result => {
                    this.graph.deleteEdge([this.click_edge.id]);
                });
            },
            addNodeToDb(x, y) {
                let data = {
                    graphId: this.graphId,
                    node: {label: "NewNode", fx: x, fy: y, type: 0, radius: 20, content: "this is a newNode"}
                };
                this.addNode(data).then(result => {
                    this.graph.addNodes({id: result.data, x: x, y: y, type: 0, r: 20});
                });
                d3ClassGetter.nodeStyleList[0].count += 1;
            },
            addEdgeToDb(source, target) {
                let temp = {
                    graphId: this.graphId,
                    sourceId: source,
                    targetId: target,
                    ship: this.new_edge_label,
                    type: this.new_edge_type
                };
                if (temp.type === "") {
                    temp.type = 0;
                }
                if (temp.ship === "") {
                    temp.ship = " ";
                }
                this.addRelation(temp).then(result => {
                    this.graph.addEdges({
                        id: result.data, source: source, target: target,
                        label: temp.ship, type: temp.type
                    });
                    d3ClassGetter.nodeStyleList[d3ClassGetter.nodeStyleList.length - 1].count += 1;
                });
            },
            changeGraphMode() {
                if (this.graphMode === 0) {
                    this.graphMode = 1;
                    this.graph.changeMode(1);
                    this.$message.success("已切换为力导图模式");
                } else {
                    this.graphMode = 0;
                    this.graph.changeMode(0);
                    this.$message.success("已切换为排版模式");
                }
            },
            exportXML() {
                this.exportGraphAsXml(this.graphId);
            },
            importGraphByFile() {
                for (let nodeStyle of d3ClassGetter.nodeStyleList) {
                    if (nodeStyle.count !== 0) {
                        this.$message.error("该图谱不为空图谱，无法导入");
                        return;
                    }
                }
                global.uploadFile(this.graphId, ".csv", this.importGraph);
                setTimeout(() => {
                    this.reload1();
                }, 5000);
            },
            resolveGraphByText() {
                this.importerState = !this.importerState;
            },
            useQA() {
                this.QAState = !this.QAState;
            },
            searchNode(str) {
                this.search({graphId: this.graphId, string: str}).then(result => {
                    this.searchResult.edges = result.data.edges;
                    this.searchResult.nodes = result.data.nodes;
                    this.searchResult.nodes_content = result.data.nodes_content;
                });
                this.drawerState[2] = true;
                this.withDrawer = true;
            },
            filterNodeType(selectedNodeType) {
                this.graph.filterNode(selectedNodeType);
            },
            displayGraphInfo() {
                this.isDisplayInfo = !this.isDisplayInfo;
            },
            showEdgeLabel() {
                this.show_edge_label = !this.show_edge_label;
                this.graph.changeEdgeLabelShow(this.show_edge_label);
            },
            changeNodeSize() {
                let temp = {id: this.click_node.id, radius: this.click_node.r, type: this.click_node.type};
                this.updateNode(temp).then(result => {
                    this.graph.modifyNodeSize({id: this.click_node.id, r: this.click_node.r});
                });
            },
            highLightNode(id) {
                this.graph.highLightNodes([parseInt(id)]);
            },
            highLightEdge(id) {
                this.graph.highLightEdges([parseInt(id)]);
            },
            changeNodeLabel(size) {
                this.graph.changeNodeLabelSize(size);
            },
            zoomIn() {
                this.graph.body.scale.k = this.graph.body.scale.k + 0.1;
                this.graph.body.emitter.emit("redraw");
            },
            zoomOut() {
                this.graph.body.scale.k = this.graph.body.scale.k - 0.1;
                this.graph.body.emitter.emit("redraw");
            },
            resumeZoom() {
                this.graph.body.scale.k = 1;
                this.graph.body.emitter.emit("redraw");
            },
            updateInfo(graph) {
                let nodes = graph.nodes;
                for (let i = 0, len = d3ClassGetter.nodeStyleList.length; i < len; i++) {
                    d3ClassGetter.nodeStyleList[i].count = nodes.filter(n => n.type === i).length;
                }
            },
            initializeGraph() {
                const option = {};
                let dom = document.querySelector("#graph");
                const bounding = dom.getBoundingClientRect();
                // 画布
                this.graph = new Graph(dom, {nodes: [], edges: []}, bounding.width, bounding.height, option);
                // 缩略图
                this.graph.thumbnail = new Thumbnail(dom, this.graph.body, this.graph.operator);
            },
            // 注册事件
            initializeEvent() {
                const canvas = this.graph.body.nodeContainer;
                d3.select(canvas)
                    .on("click", () => {
                        return this.graph.body.emitter.emit("tap", d3.mouse(canvas), d3.event, params => {
                            if (params && params.len > 1) {
                                params = params[0];
                            }
                            for (let i = 0; i < this.drawerState.length; ++i) {
                                this.drawerState[i] = false;
                            }
                            if (params instanceof Node) {
                                this.click_node = params;
                                this.drawerState[0] = true;
                                this.withDrawer = true;
                                if (!this.new_edge_flag) {
                                    this.new_edge_source_id = this.click_node.id;
                                } else {
                                    this.addEdgeToDb(this.new_edge_source_id, this.click_node.id);
                                    // this.graph.addEdges({source: this.new_edge_source_id, target: this.click_node.id});
                                    this.set_new_link_flag(false);
                                }
                            } else if (params instanceof Edge) {
                                this.drawerState[1] = true;
                                this.withDrawer = true;
                                this.click_edge = params;

                            } else {
                                // this.withDrawer = false;
                            }
                            if (this.new_node_flag) {
                                this.addNodeToDb(d3.event.offsetX, d3.event.offsetY);
                                this.set_new_node_flag(false);
                            }

                            this.clickEvent(d3.mouse(canvas), d3.event, params);
                        });
                    })
                    .on("contextmenu", () => this.graph.body.emitter.emit("tap", d3.mouse(canvas), d3.event, params => {
                        // 阻止默认右键事件
                        d3.event.returnValue = false;
                        console.log("右键");
                        this.set_new_node_flag(false);
                    }))
                    .on("dblclick", () => this.graph.body.emitter.emit("tap", d3.mouse(canvas), d3.event, params => {
                        console.log("双击");
                        this.set_new_node_flag(false);
                    }))
                    .on("mouseover", () => {
                        console.log("进来了");
                    })
                    .on("mouseout", () => {
                        console.log("出来了");
                    });


                // 注册窗口resize事件
                d3.select(window).on("resize", () => {
                    let width = document.getElementById("graph").clientWidth;
                    let height = document.getElementById("graph").clientHeight;
                    this.graph.body.emitter.emit("resize", width, height);
                });
            },
            /** 加载数据 */
            loadData() {
                // 延时
                setTimeout(() => {
                    this.graph.setData(defaultDatas);
                    d3ClassGetter.title.back = true;
                    d3ClassGetter.title.isGraph = true;
                });
            },
            /** 点击事件 */
            clickEvent(coordinates, evt, obj) {
                if (obj && obj instanceof Node) {
                    const oldStatus = obj.status;
                    obj.status = oldStatus === Status.selection ? Status.default : Status.selection;
                    this.graph.body.emitter.emit("click.node");
                } else if (obj && obj instanceof Edge) {
                    const oldStatus = obj.status;
                    obj.status = oldStatus === Status.selection ? Status.default : Status.selection;
                    this.graph.body.emitter.emit("redrawEdges");
                } else {
                    for (let node of this.graph.body.transformData.nodes) {
                        node.status = Status.default;
                    }
                    for (let edge of this.graph.body.transformData.edges) {
                        edge.status = Status.default;
                    }
                    this.graph.body.emitter.emit("redraw");
                }
            },
            handleClose(done) {
                d3ClassGetter.newUser++;
                done();
            }
        }
    };
</script>

<style scoped>
    @import "../assets/styles/bench.css";

    .vertical-wrapper {
        display: flex;
        flex-flow: column;
        position: relative;
        width: 100%;
        height: 100%;
        margin: auto;
    }

    .bench-wrapper {
        position: relative;
        margin: auto;
        min-height: calc(100% - 100px);
        width: 70%;

        padding: 14px;
        border-radius: 10px;
        box-shadow: 0 0 3px 3px #eeeeee;
        z-index: 0;

        background-color: white;
    }

    .charts-bench {
        width: 100%;
        height: 100%;
    }

    .tools-wrapper {
        display: flex;
        justify-content: center;
        align-items: center;
        vertical-align: middle;

        height: 56px;
        width: 88%;
        margin: 0 auto 10px auto;
        font-size: 13px;

        border-bottom: 1px solid #eeeeee;
    }
</style>